from transitions import Machine
from infoUi import myInfoUi
from infoUi import wx
from threading import Timer
import time

#ota状态进入退出动作callback
class stateDeal(myInfoUi):
    def initTimer(self):
        self.__StatusTimer=''
        self.__timerOwner = ''

    def timeOutHandle(self):
        self.errorDebug(" %s %s timeOut !\r\n" %(self.otaConfig['curStatus'], self.state))
        self.otaConfig['curStatus'] = ''
        self.otaRest()

    def timerStart(self):
        if(self.state != self.__timerOwner):
            if(self.__StatusTimer != '' and self.__timerOwner != '' \
                and self.__StatusTimer.is_alive()):
                self.__StatusTimer.cancel()
                print("%s timer stop" %(self.__timerOwner))
                self.__StatusTimer=''

            self.__StatusTimer = Timer(int(self.stateMacConf[self.state]), self.timeOutHandle)
            self.__StatusTimer.start()
            print("%s timer start" %(self.state))
            self.__timerOwner = self.state

    def timerStop(self):
        if(self.__StatusTimer != ''):
            self.__StatusTimer.cancel()
            self.__StatusTimer=''

    def doNothing(self):
        pass

    def onIdel(self):
        self.statusGaugeSetValue(0)
        self.statusGaugeHide()
        self.statusTextSet(2,self.state)
        self.otaConfig['curStatus']=''
        if(self.__StatusTimer.is_alive()):
            self.__StatusTimer.cancel()
            print("%s timer stop" %(self.__timerOwner))
        self.__timerOwner = ''
        print("onIdel!\r\n")
        pass
    def onPrepare(self):
        pass
    def onCheckSim(self):
        self.timerStart()
        self.statusTextSet(2,self.state)
        print("onReady!\r\n")
        pass
    def onCheckNet(self):
        self.timerStart()
        self.statusTextSet(2,self.state)
        print("onConnect!\r\n")
        pass
    def onCmdSend(self):
        self.timerStart()
        self.statusTextSet(2,self.state)
        print("onOnline!\r\n")
        pass
    def onDownloading(self):
        self.timerStart()
        self.statusGaugeSetValue(0)
        self.statusGaugeShow()
        self.statusTextSet(2,self.state)
        print("onDownloading!\r\n")
        pass
    def onUpdateing(self):
        self.timerStart()
        self.statusGaugeSetValue(0)
        self.statusGaugeShow()
        self.statusTextSet(2,self.state)
        print("onUpdateing!\r\n")
        pass
    def onSuccess(self):
        print("onSuccess!\r\n")
        self.statusTextSet(2,self.state)
        curState = self.otaConfig['curStatus']
        if(curState != '' and self.otaUiStatusTable[curState] != ''):
            self.otaConfig['curStatus'] = self.otaUiStatusTable[curState]
            print('new state %s, old state %s' %(self.otaConfig['curStatus'],curState))
            self.otaStart()
            return None

        self.debugToUi("****** Ota test success! ******\r\n")
        self.otaConfig['curStatus'] = ''
        self.otaRest()
        pass



#ota 状态机
class otaStateMac(stateDeal):
    def onPrepare(self):
        try:
            self.otaStart()
        except Exception as e:
            print("onPrepare:%s " %(e))
        pass

    def initMachine(self):
        self.initTimer()
    # 状态定义
        self.states=[
            {'name':'otaIdle', 'on_enter':['onIdel'], 'on_exit':['doNothing']},
            {'name':'otaReady', 'on_enter':['onPrepare'], 'on_exit':['doNothing']},
            {'name':'otaCheckSim', 'on_enter':['onCheckSim'], 'on_exit':['doNothing']},
            {'name':'otaCheckNet', 'on_enter':['onCheckNet'], 'on_exit':['doNothing']},
            {'name':'otaCmdSend', 'on_enter':['onCmdSend'], 'on_exit':['doNothing']},
            {'name':'otaDownloading', 'on_enter':['onDownloading'], 'on_exit':['doNothing']},
            {'name':'otaUpdateing', 'on_enter':['onUpdateing'], 'on_exit':['doNothing']},
            {'name':'otaSuccess', 'on_enter':['onSuccess'], 'on_exit':['doNothing']},
            ]

    # 定义状态转移
    # The trigger argument defines the name of the new triggering method
        self.transitions = [
            {'trigger': 'otaPrepare', 'source': 'otaIdle', 'dest': 'otaReady' },
            {'trigger': 'otaStart', 'source': ['otaReady','otaCheckSim','otaSuccess'], 'dest': 'otaCheckSim' },
            {'trigger': 'otaLink', 'source': ['otaCheckSim','otaCheckNet'], 'dest': 'otaCheckNet'},
            {'trigger': 'otaOnline', 'source': 'otaCheckNet', 'dest': 'otaCmdSend'},
            {'trigger': 'otaWaitDownload', 'source': 'otaCmdSend', 'dest': 'otaDownloading'},
            {'trigger': 'otaWaitUpdate', 'source': ['otaDownloading','otaCmdSend'], 'dest': 'otaUpdateing' },
            {'trigger': 'otaCompleted', 'source': 'otaUpdateing', 'dest': 'otaSuccess'},
            {'trigger': 'otaRest', 'source': '*', 'dest': 'otaIdle'},
        ]

    # 初始化
        self.machine = Machine(model=self, states=self.states, transitions=self.transitions, initial=self.states[0]['name'])
    pass


#定义自己的状态机
class myStateMachine(otaStateMac):

    def waitReady(self,data):
        return 1
        pass

    def waitSIMOk(self,data):
        #忽略AT的回显
        if('+CPIN:' not in str(data) and \
            'ERROR:' not in str(data)):
            return 1
        #检索值 'OK'
        if('READY' in str(data)):
            try:
                self.otaLink()
            except Exception as e:
                print("waitSIMOk:%s " %(e))
            return 1
        else:
            time.sleep(1)
            try:
                self.otaStart()
            except Exception as e:
                print("waitSIMOk:%s " %(e))
            return 1

    def waitLinkOn(self,data):
        #检索值 'NO SERVICE'
        #忽略非+CPSI上报
        if('+CPSI:' not in str(data) and \
            'ERROR' not in str(data)):
            return 1

        if('NO SERVICE' in str(data)):
            #3次检测不到网络,返回0
            time.sleep(1)
            try:
                self.otaLink()
            except Exception as e:
                print("waitLinkOn:%s " %(e))
            return 1
        else:
            try:
                self.otaOnline()
            except Exception as e:
                print("waitLinkOn:%s " %(e))
            return 1

    def waitDownloadStart(self,data):
        #忽略非+CFOTA上报
        if('*ATREADY' in str(data)):
            return 0

        if('+CFOTA:' not in str(data) and \
        'ERROR' not in str(data)):
            return 1
        if('FOTA,START' in str(data)):
            try:
                self.otaWaitDownload()
            except Exception as e:
                print("waitDownloadStart:%s " %(e))
            return 1

        if('DOWNLOADING:' in str(data)):
            #差分包太小会直接跳到100
            if('DOWNLOADING:100' in str(data)):
                try:
                    self.otaWaitUpdate()
                except Exception as e:
                    print("waitDownloadStart:%s " %(e))
            else:
                try:
                    self.otaWaitDownload()
                except Exception as e:
                    print("waitDownloadStart:%s " %(e))
            return 1
        else:
            return 0

    def waitDownloadCompleted(self,data):
        #忽略非+CFOTA上报
        if('+CFOTA:' not in str(data) and \
        'ERROR' not in str(data)):
            return 1
        #检索值 'DOWNLOADING:100'
        if('DOWNLOADING' in str(data)):
            if(':100' in str(data)):
                self.statusGaugeSetValue(100)
                time.sleep(2)
                try:
                    self.otaWaitUpdate()
                except Exception as e:
                    print("waitDownloadCompleted:%s " %(e))
                return 1
            else:
                dataList = str(data).split(':',2)
                #设置进度条
                loading = dataList[2]
                loading = dataList[2]
                value = int(''.join(filter(str.isdigit, loading)))
                self.statusGaugeSetValue(value)
                return 1
        else:
            return 0

    def waitUpdateCompleted(self,data):
        #忽略非+CFOTA上报
        if('+CFOTA:' not in str(data) and \
        'ERROR' not in str(data)):
            return 1
        #检索值 'UPDATE SUCCESS'
        if('UPDATE' in str(data)):
            if('SUCCESS' in str(data)):
                try:
                    self.otaCompleted()
                except Exception as e:
                    print("waitUpdateCompleted:%s " %(e))
                #检索成功
                return 1
            elif('ERROR' in str(data)):
                return 0
            elif('FAIL' in str(data)):
                return 0
            else:
                dataList = str(data).split(':',2)
                #设置进度条
                loading = dataList[2]
                value = int(''.join(filter(str.isdigit, loading)))
                self.statusGaugeSetValue(value)
                if(value == 100):
                    time.sleep(2)
                return 1
        else:
            return 0

    def waitSuccess(self,data):
        return 1
        pass

    def waitIdle(self):
        return 1
        pass

    def setUpMyStateMac(self):
        self.__netCheckCount = 0
        self.__atCheckCount = 0
        self.initMachine()
        self.dealWay = {
            'otaIdle': self.waitIdle,
            'otaReady': self.waitReady,
            'otaCheckSim': self.waitSIMOk,
            'otaCheckNet': self.waitLinkOn,
            'otaCmdSend': self.waitDownloadStart,
            'otaDownloading': self.waitDownloadCompleted,
            'otaUpdateing': self.waitUpdateCompleted,
            'otaSuccess': self.waitSuccess
        }

#machine demo
if __name__ == '__main__':
    model = myStateMachine()
    model.setUpMyStateMac()
    model.otaStart()
    model.otaStart()
    model.otaConnectModel()
    model.otaConnectModel()
    model.otaConnectNet()
    model.otaWaitDownload()
    model.otaWaitUpdate()
    model.otaCompleted()

    func = model.dealWay.get('otaSuccess')
    if(func != None):
        func("1234")



